
#include <string.h>
#include <stdlib.h>
//#include "../client/client.h"
#include "../twofish/myTwofish2.h"
#include "myRsa.h"

#define PADDING_SIZE	11						/* Value depends on the padding scheme*/
												/* More padding is safer */
#define PADDING			RSA_PKCS1_PADDING
char * publicEncrypt(char * from, RSA * rsa)
{
	int encryptedSize;
	char * encrypted;
	
	
	encryptedSize = RSA_size(rsa);
	
	if((encrypted = malloc(encryptedSize))==NULL)
		return NULL;
	
	if((RSA_public_encrypt(strlen(from), from, encrypted, rsa, PADDING))==-1)
   			return NULL;
	
	return encrypted;
	
}


char * privateEncrypt(unsigned char *from, RSA *key)
{
	int encryptedSize;
	char error[121];
	unsigned char * p1, * p2;
	unsigned char * enc1, *enc2, * final;
	
	
	encryptedSize = RSA_size(key);
	
	if((p1=malloc( encryptedSize / 2)) == NULL)
			return NULL;
	
	memcpy(p1, from, encryptedSize / 2);
	
	if((p2=malloc( encryptedSize / 2)) == NULL)
				return NULL;

	memcpy(p2, from + encryptedSize / 2, encryptedSize / 2);
	
	
	if((enc1 = malloc(encryptedSize))==NULL)
		return NULL;
		
	if((enc2 = malloc(encryptedSize))==NULL)
		return NULL;
	
	if((RSA_private_encrypt(encryptedSize / 2, p1, enc1, key, PADDING))==-1)
		return NULL;
	
	if((RSA_private_encrypt(encryptedSize / 2, p2, enc2, key, PADDING))==-1)
		return NULL;
	
	if((final = malloc(2 * encryptedSize))==NULL)
		return NULL;

	memcpy(final,enc1, encryptedSize );
	memcpy(final + encryptedSize, enc2, encryptedSize );

	return final;
}

Imprime(char * encriptado, int size)
{
	int i = 0;
	while(i < size)
	{
		putchar(encriptado[i]);
		i++;
	}
}

char * publicDecrypt(char * from, RSA * rsa)
{
	int encryptedSize;
	char error[121];
	unsigned char * p1, * p2;
	unsigned char * dec1, * dec2, * final;
		
	encryptedSize = RSA_size(rsa) * 2;
		
	if((p1=malloc( encryptedSize / 2)) == NULL)
			return NULL;
	
	memcpy(p1, from, encryptedSize / 2);
	
	if((p2=malloc( encryptedSize / 2)) == NULL)
			return NULL;
	
	memcpy(p2, from + encryptedSize / 2, encryptedSize / 2);

	
	if((dec1 = calloc(encryptedSize / 2 - PADDING_SIZE, 1))==NULL)
		return NULL;
	
	if((dec2 = calloc(encryptedSize / 2 - PADDING_SIZE, 1))==NULL)
		return NULL;
	
	if((RSA_public_decrypt(encryptedSize / 2, p1, dec1, rsa, PADDING))==-1)
		return NULL;
	
	if((RSA_public_decrypt(encryptedSize / 2, p2, dec2, rsa, PADDING))==-1)
		return NULL;
	
	if((final = malloc(encryptedSize/2))==NULL)
		return NULL;
	
	memcpy(final,dec1, encryptedSize / 4 );
	memcpy(final + encryptedSize / 4, dec2, encryptedSize / 4);
		
	return final;
}

char * privateDecrypt(char * from, RSA * rsa)
{
	int encryptedSize;
	char * decrypted;
	char error[121];
	encryptedSize = RSA_size(rsa);
	
	if((decrypted = calloc(encryptedSize - PADDING, 1))==NULL)
		return NULL;
	
	if((RSA_private_decrypt(encryptedSize, from, decrypted, rsa, PADDING))==-1)
		return NULL;
	
	return decrypted;
}

#define EXPONENT	65537


int 
RSA_bn2str(const BIGNUM *bn,char *s)
{
	int pos = 0;
	int length;
	char *tmp;
	
	/* If that part of the structure is not available, put a 0 */
	if( bn == NULL )
	{
		s[pos++]='0';
	}
	else
	{
		tmp = BN_bn2hex(bn);
		length = strlen(tmp);
		strncpy(s, tmp,length);
		pos = pos + length;
		OPENSSL_free(tmp);
	}
	s[pos]='\0';
	
	return pos;
}


int 
RSA_key2str(const RSA *key,char *s)
{
	int length;
	int ans=0;
	
	length = RSA_bn2str(key->n,s) + 1; /* + 1 because of the finishing '\0' */
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->e,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->d,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->p,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->q,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->dmp1,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->dmq1,s) + 1;
	ans = ans + length;
	s = s + length;
	length = RSA_bn2str(key->iqmp,s) + 1;
	ans = ans + length;
	s = s + length;
	
	return ans;
}


RSA *
RSA_str2key(const char *s)
{
	RSA *key;
	int length;
	
	key = RSA_new();
	
	length = BN_hex2bn(&(key->n),s);
	s = s + length + 1;
	if( BN_is_zero(key->n) )
	{	
		BN_free(key->n);
		key->n = NULL;
	}
	length = BN_hex2bn(&(key->e),s);
	s = s + length + 1;
	if( BN_is_zero(key->e) )
	{	
		BN_free(key->e);
		key->e = NULL;
	}
	length = BN_hex2bn(&(key->d),s);
	s = s + length + 1;
	if( BN_is_zero(key->d) )
	{	
		BN_free(key->d);
		key->d = NULL;
	}
	length = BN_hex2bn(&(key->p),s);
	s = s + length + 1;
	if( BN_is_zero(key->p) )
	{	
		BN_free(key->p);
		key->p = NULL;
	}
	length = BN_hex2bn(&(key->q),s);
	s = s + length + 1;
	if( BN_is_zero(key->q) )
	{	
		BN_free(key->q);
		key->q = NULL;
	}
	length = BN_hex2bn(&(key->dmp1),s);
	s = s + length + 1;
	if( BN_is_zero(key->dmp1) )
	{	
		BN_free(key->dmp1);
		key->dmp1 = NULL;
	}
	length = BN_hex2bn(&(key->dmq1),s);
	s = s + length + 1;
	if( BN_is_zero(key->dmq1) )
	{	
		BN_free(key->dmq1);
		key->dmq1 = NULL;
	}
	length = BN_hex2bn(&(key->iqmp),s);
	s = s + length + 1;
	if( BN_is_zero(key->iqmp) )
	{	
		BN_free(key->iqmp);
		key->iqmp = NULL;
	}
	
	return key;
}

/*
int
exportPublicKey(const RSA *key,const char *fileName)
{
	RSA *tmp;
	char *keyString;
	int length;
	FILE *file;
	
	if( (keyString = malloc( 1024 * 8 + 8 + 1 ) ) == NULL )
		return 1;
	
	/* Back up of the original key 
	if( RSA_key2str(key,keyString) == 0)
	{	
		free(keyString);
		return 1;
	}
	if( (tmp = RSA_str2key(keyString)) == NULL)
	{	
		free(keyString);
		return 1;
	}
	
	/* Erase the private part of the key and export 
	//shareKey(tmp);
	length = RSA_key2str(tmp,keyString);
	if( (file = fopen(fileName,"w")) == NULL )
	{	
		free(keyString);
		RSA_free(tmp);
		return 1;
	}
	if( fwrite(keyString,1,length,file) != length )
	{	
		free(keyString);
		RSA_free(tmp);
		fclose(file);
		return 1;
	}
	free(keyString);
	RSA_free(tmp);
	fclose(file);

	return 0;
}
int
exportPrivateKey(const RSA * key,char *fileName,char *pass)
{
	char *keyString;
	int length;
	FILE *file;
	
	if( (keyString = malloc( 1024 * 8 + 8 + 1 )) == NULL )
		return 1;
	
	length = RSA_key2str(key,keyString);
		
	if( (file = fopen(fileName,"w")) == NULL )
	{	
		free(keyString);
		return 1;
	}
	if( fwrite(keyString,1,length,file) != length )
	{	
		free(keyString);
		return 1;
	}
	fclose(file);
	Twofish_enc(2,RSA_size(key), fileName, pass); /*MODE_CBC
	
	free(keyString);
	
	return 0;
}

int
importPublicKey(const char *fileName,RSA **key)
{
	char *keyString;
	int length;
	int character;
	FILE *file;
	
	*key = RSA_new();

	if( (keyString = malloc( 1024 * 8 + 8 + 1 )) == NULL )
		return 1;

	/* Import key 
	if( (file = fopen(fileName,"r")) == NULL )
	{	
		free(keyString);
		return 1;
	}
	length = 0;
	while( (character = fgetc(file)) != EOF )
		keyString[length++]=character;
	*key = RSA_str2key(keyString);
	
	free(keyString);
	fclose(file);
	
	return 0;
}

int
importPrivateKey(const char *fileName, RSA **key, const char *pass)
{
	char *keyString;
	int length;
	int character;
	char encFilename[128];
	FILE *file;
	
	*key = RSA_new();
	sprintf(encFilename,"%s.cry", fileName);
	Twofish_dec(2, 128, encFilename, NULL); /*MODE_CBC
	
	if( (keyString = malloc( 1024 * 8 + 8 + 1 )) == NULL )
		return 1;

	/* Import key 
	if( (file = fopen(fileName,"r")) == NULL )
	{	
		free(keyString);
		return 1;
	}
	length = 0;
	
	while( (character = fgetc(file)) != EOF )
		keyString[length++]=character;
	
	*key = RSA_str2key(keyString);
	
	free(keyString);
	fclose(file);
	
	return 0;
}*/



